package com.topvision.auth.controller;

import com.topvision.auth.domain.SysUser;
import com.topvision.auth.domain.SysUserAccount;
import com.topvision.auth.dto.LoginDTO;
import com.topvision.auth.dto.PasswordDTO;
import com.topvision.auth.dto.RegDTO;
import com.topvision.auth.dto.UserDTO;
import com.topvision.auth.service.AuthService;
import com.topvision.auth.service.LoginService;
import com.topvision.auth.service.SysUserAccountService;
import com.topvision.auth.service.SysUserService;
import com.topvision.auth.util.Constants;
import com.topvision.auth.util.mail.MailService;
import com.topvision.common.response.ErrorResponse;
import com.topvision.common.response.SuccessResponse;
import com.topvision.common.security.DESCodec;
import com.topvision.common.security.RDes;
import com.topvision.common.utils.Responses;
import com.topvision.utils.base.JsonResult;
import com.topvision.utils.web.HeaderUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.security.NoSuchAlgorithmException;
import java.security.Principal;
import java.util.Map;
import java.util.Optional;

@RestController
@RequestMapping("/auth")
@Api(value = "认证管理", description = "用户登录、刷新TOKEN")
@Slf4j
public class AuthController {

    @Autowired
    private AuthService authService;


    @Autowired
    private LoginService loginService;

    @Autowired
    private MailService mailService;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private SysUserAccountService sysUserAccountService;

    @Autowired
    private SysUserService sysUserService;

    @ApiOperation(value = "注册")
    //  @ApiImplicitParam(name = "addedUser", value = "用户实体", required = true, dataType = "RegDTO")
    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public JsonResult<SysUser> register(@RequestBody RegDTO regDTO) {
        return authService.register(regDTO);
    }


    @ApiOperation(value = "查重")
    // @ApiImplicitParam(name = "addedUser", value = "用户实体", required = true, dataType = "String")
    @RequestMapping(value = "/checkAccount/{account:.+}", method = RequestMethod.GET)
    public ResponseEntity checkAccount(@PathVariable String account) {
        SysUserAccount userAccount = authService.checkAccount(account);
        if (userAccount != null) {
            return ResponseEntity.ok()
                    .headers(HeaderUtil.createAlert("查重用户", account))
                    .body(SuccessResponse.of("查重成功", userAccount));
        }
        return ResponseEntity.ok()
                .headers(HeaderUtil.createAlert("查重用户", account))
                .body(ErrorResponse.of("-1", account));

    }


    @ApiOperation(value = "验证邮件code")
    //@ApiImplicitParam(name = "resetPassword", value = "用户账号", required = true, dataType = "String")
    @RequestMapping(value = "/verify/{code:.+}", method = RequestMethod.GET)
    public ResponseEntity verify(@PathVariable String code) {

        String rawKey = null;
        try {
            rawKey = RDes.decrypt(code, Constants.DES_KEY);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String[] params = rawKey.split("=");
        //判断失效code
        Long ts = System.currentTimeMillis();
        Long tse = Long.valueOf(params[0]) - 10 * 60 * 1000;
        Long tt = Long.valueOf(params[0]);
        if (ts > tse && tt > ts) {
            return ResponseEntity.ok()
                    .headers(HeaderUtil.createAlert("valid key", params[1]))
                    .body(SuccessResponse.of(params[1]));

        } else {
            return ResponseEntity.ok()
                    .headers(HeaderUtil.createAlert("invalid key", params[1]))
                    .body(ErrorResponse.of("-1", "invalid key"));
        }

    }


    @ApiOperation(value = "修改密码")
    //@ApiImplicitParam(name = "resetPassword", value = "用户账号", required = true, dataType = "String")
    @RequestMapping(value = "/modifyPassword", method = RequestMethod.POST)
    public ResponseEntity modifyPassword(@RequestBody PasswordDTO passwordDTO) {

        if (passwordDTO != null) {
            String account = passwordDTO.getAccount();
            String password = passwordDTO.getPassword();

            //取出account
            SysUserAccount userAccount = authService.checkAccount(account);

            userAccount.setPassword(bCryptPasswordEncoder.encode(password));
            sysUserAccountService.save(userAccount);
            return ResponseEntity.ok()
                    .headers(HeaderUtil.createAlert("", ""))
                    .body(SuccessResponse.of("修改成功"));
        } else {
            return ResponseEntity.ok()
                    .headers(HeaderUtil.createAlert("empty", "empty data"))
                    .body(ErrorResponse.of("-1", "empty data"));
        }


    }

    @ApiOperation(value = "获取用户信息")
    @RequestMapping(value = "/userInfo", method = RequestMethod.POST)
    public ResponseEntity userInfo(Principal principal) {
        String userName = principal.getName();
        Optional<SysUser> sysUser = Optional.empty();
        if (userName != null) {
            sysUser = sysUserService.findByUserName(userName);
        }
        return sysUser.map(user -> {
            return ResponseEntity.ok().body(SuccessResponse.of(user));
        }).orElse(ResponseEntity.ok().body(SuccessResponse.of("empty")));
    }


    @ApiOperation(value = "修改个人信息")
    @RequestMapping(value = "/profile", method = RequestMethod.POST)
    public ResponseEntity profile(@RequestBody UserDTO userDTO, Principal principal) {

        String userName = principal.getName();
        Optional<SysUser> sysUser = Optional.empty();
        if (userName != null) {
            sysUser = sysUserService.findByUserName(userName);
        }
        return sysUser.map(user -> {
            if (StringUtils.isNotBlank(userDTO.getMobile())) {
                user.setMobile(userDTO.getMobile());
            }

            if (StringUtils.isNotBlank(userDTO.getAddress())) {
                user.setAddress(userDTO.getAddress());
            }
            if (StringUtils.isNotBlank(userDTO.getCompany())) {
                user.setCompany(userDTO.getCompany());
            }

            if (StringUtils.isNotBlank(userDTO.getJobTitle())) {
                user.setJobTile(userDTO.getJobTitle());
            }

            if (StringUtils.isNotBlank(userDTO.getTrueName())) {
                user.setTrueName(userDTO.getTrueName());
            }

            sysUserService.save(user);
            return ResponseEntity.ok().body(SuccessResponse.of());
        }).orElse(ResponseEntity.ok().body(SuccessResponse.of()));
    }


    @ApiOperation(value = "重置密码发送邮件")
    // @ApiImplicitParam(name = "resetEmail", value = "用户账号", required = true, dataType = "String")
    @RequestMapping(value = "/resetEmail/{account:.+}", method = RequestMethod.GET)
    public ResponseEntity resetEmail(@PathVariable String account) {
        StringBuffer url = new StringBuffer();

        Long ts = System.currentTimeMillis() + 10 * 60 * 1000;
        String rawKey = ts.toString() + "=" + account;
        String enkey = null;
        try {
            enkey = RDes.encrypt(rawKey, Constants.DES_KEY);
        } catch (Exception e) {
            e.printStackTrace();
        }

        url.append("http://localhost:8080/uaa/auth");
        url.append("/resetPassword/");
        url.append(enkey);


        StringBuffer content = new StringBuffer();
        content.append("<!DOCTYPE html>");
        content.append("<html><head><meta http-equiv=\\\"Content-Type\\\" content=\\\"text/html; charset=UTF-8\\\">");
        content.append("<title>Insert title here</title>");
        content.append("</head><body>");
        content.append("<div style=\\\"width:600px;height:400px;margin:50px auto;\\\">");
        content.append("<h1>鼎视科技密码重置</h1><br/><br/>");
        content.append("<p>请点击如下链接，完成密码重置，此链接10分钟内有效，请注意失效，如点击链接失效，请将链接地址复制到浏览器地址栏访问！！</p><br/>");
        content.append("<p>" + url.toString() + "</p><br/>");
        content.append("<a href=" + '"' + url.toString() + '"' + ">Reset Password</a>");
        content.append("</div>");
        content.append("</body></html>");


        mailService.sendHtmlMail(account, "重置密码邮件", content.toString());

      /*  String content =
        mailService.sendSimpleMail(account,"密码重置邮件",content);*/
        return ResponseEntity.ok()
                .headers(HeaderUtil.createAlert("resetpassword", account))
                .body(SuccessResponse.of(account));
    }


    /**
     * 授权登录
     *
     * @param loginDTO
     * @param response
     * @return
     */
    @ApiOperation(value = "授权登录", produces = MediaType.APPLICATION_JSON_VALUE, notes = "用户授权登录接口", response = SuccessResponse.class)
    @PostMapping(value = "/auth/token", produces = MediaType.APPLICATION_JSON_VALUE)
    public ResponseEntity authorize(@Valid @RequestBody LoginDTO loginDTO, BindingResult result, HttpServletResponse response) {
        log.debug("REST request to login：{}", loginDTO);
        if (result.hasErrors()) {
            return Responses.validate(result);
        }

        Map<String, Object> tokenMap = loginService.authorize(loginDTO.getUsername(), loginDTO.getPassword(), loginDTO.getRememberMe());
        response.addHeader(HttpHeaders.AUTHORIZATION, "Bearer " + tokenMap.get("access_token"));
        return ResponseEntity.ok(SuccessResponse.of("授权登录成功", tokenMap));
    }
}
